package Service;

import Service.SecurityData;
import Service.ADJUSTMENTFACTOR;
import UI.ClientTickDataCache;
import facecat.topin.core.*;
import java.util.*;
  
/*
 * 股票服务
 */
public class StockService {
    /*
     * 获取指定年月日的星期
     *@param year 年
     *@param month 月
     *@param day 日
     */
    public static int dayOfWeek(int y, int m, int d)
    {
        if (m == 1 || m == 2)
        {
            m += 12;
            y--;
        }
        return (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;
    }

    /*
     * 获取季度
     */
    public static int getSeason(int month)
    {
        if (month >= 1 && month <= 3)
        {
            return 1;
        }
        else if (month >= 4 && month <= 6)
        {
            return 2;
        }
        else if (month >= 7 && month <= 9)
        {
            return 3;
        }
        else
        {
            return 4;
        }
    }

    /*
     * 合并最新数据
     *@param oldDatas 老数据
     *@param latestData 新数据
     *@param tickDataCache TICK数据
     *@param cycle 周期
     */
    public static void mergeLatestData(String code, ArrayList<SecurityData> oldDatas, SecurityData latestData, ClientTickDataCache tickDataCache, int dCycle)
    {
        int cycle = dCycle;
        if (cycle == 0)
        {
            cycle = 1;
        }
        if (latestData.m_open <= 0 || latestData.m_volume <= 0 || latestData.m_amount <= 0)
        {
            return;
        }
//        DateTime newDate = FCTran.numToDate(latestData.m_date);
        Calendar newDate = FCTran.numToDate(latestData.m_date);
        if (newDate.get(Calendar.HOUR_OF_DAY) * 60 + newDate.get(Calendar.MINUTE) < 570)
        {
            newDate = new GregorianCalendar(newDate.get(Calendar.YEAR), newDate.get(Calendar.MONTH) + 1, newDate.get(Calendar.DAY_OF_MONTH), 9, 30 ,0);
            latestData.m_date = FCTran.dateToNum(newDate);
        }
        //A股
        else if (newDate.get(Calendar.HOUR_OF_DAY) * 60 + newDate.get(Calendar.MINUTE) < 571)
        {
            newDate = new GregorianCalendar(newDate.get(Calendar.YEAR), newDate.get(Calendar.MONTH) + 1, newDate.get(Calendar.DAY_OF_MONTH), 9, 31, 0);
            latestData.m_date = FCTran.dateToNum(newDate);
        }
        else if (newDate.get(Calendar.HOUR_OF_DAY) * 60 + newDate.get(Calendar.MINUTE) > 900)
        {
            newDate = new GregorianCalendar(newDate.get(Calendar.YEAR), newDate.get(Calendar.MONTH) + 1, newDate.get(Calendar.DAY_OF_MONTH), 15, 0, 0);
            latestData.m_date = FCTran.dateToNum(newDate);
        }
        else if (newDate.get(Calendar.HOUR_OF_DAY) * 60 + newDate.get(Calendar.MINUTE) > 690 && newDate.get(Calendar.HOUR_OF_DAY) * 60 + newDate.get(Calendar.MINUTE) < 780)
        {
            newDate = new GregorianCalendar(newDate.get(Calendar.YEAR), newDate.get(Calendar.MONTH) + 1, newDate.get(Calendar.DAY_OF_MONTH), 11, 30, 0);
            latestData.m_date = FCTran.dateToNum(newDate);
        }
        boolean isNextCycle = true;
        if (dCycle == 0)
        {
            isNextCycle = false;
        }
        else if (cycle < 1440)
        {
            if (oldDatas.size() > 0)
            {
                int newMinutes = (int)(latestData.m_date / 60);
                int lastMinutes = (int)(oldDatas.get(oldDatas.size() - 1).m_date / 60);
                isNextCycle = newMinutes - lastMinutes >= cycle;
            }
        }
        else
        {
            if (cycle == 1440)
            {
                if (oldDatas.size() > 0)
                {
                    Calendar lastDate = FCTran.numToDate(oldDatas.get(oldDatas.size() - 1).m_date);
                    isNextCycle = FCTran.dateToNum(new GregorianCalendar(newDate.get(Calendar.YEAR), newDate.get(Calendar.MONTH) + 1, newDate.get(Calendar.DAY_OF_MONTH)))
                    != FCTran.dateToNum(new GregorianCalendar(lastDate.get(Calendar.YEAR), lastDate.get(Calendar.MONTH) + 1, lastDate.get(Calendar.DAY_OF_MONTH)));
                }
            }
            else if (cycle == 10080)
            {
                if (oldDatas.size() > 0)
                {
                    double firstDate = FCTran.getDateNum(1970, 1, 5, 0, 0, 0, 0);
                    int lWeeks = (int)((oldDatas.get(oldDatas.size() - 1).m_date - firstDate) / 86400) / 7;
                    int weeks = (int)((latestData.m_date - firstDate) / 86400) / 7;
                    if (weeks > lWeeks)
                    {
                        isNextCycle = true;
                    }
                    else
                    {
                        isNextCycle = false;
                    }
                }
            }
            else if (cycle == 43200)
            {
                if (oldDatas.size() > 0)
                {
                    Calendar lastDate = FCTran.numToDate(oldDatas.get(oldDatas.size() - 1).m_date);
                    isNextCycle = (newDate.get(Calendar.YEAR) * 12 + newDate.get(Calendar.MONTH) + 1 != lastDate.get(Calendar.YEAR)* 12 + lastDate.get(Calendar.MONTH) + 1);
                }
            }
            else if (cycle == 129600)
            {
                if (oldDatas.size() > 0)
                {
                    Calendar lastDate = FCTran.numToDate(oldDatas.get(oldDatas.size() - 1).m_date);
                    isNextCycle = newDate.get(Calendar.YEAR) * 4 + getSeason(newDate.get(Calendar.MONTH) + 1) != lastDate.get(Calendar.YEAR) * 4 + getSeason(lastDate.get(Calendar.MONTH) + 1);
                }
            }
            else if (cycle == 259200)
            {
                if (oldDatas.size() > 0)
                {
                    Calendar lastDate = FCTran.numToDate(oldDatas.get(oldDatas.size() - 1).m_date);
                    isNextCycle = newDate.get(Calendar.YEAR) * 2 + (newDate.get(Calendar.MONTH) + 1 - 1) / 6 != lastDate.get(Calendar.YEAR) * 2 + (lastDate.get(Calendar.MONTH) + 1 - 1) / 6;
                }
            }
            else if (cycle == 518400)
            {
                if (oldDatas.size() > 0)
                {
                    Calendar lastDate = FCTran.numToDate(oldDatas.get(oldDatas.size() - 1).m_date);
                    isNextCycle = newDate.get(Calendar.YEAR) != lastDate.get(Calendar.YEAR);
                }
            }
        }
        if (isNextCycle)
        {
            SecurityData newCycleData = new SecurityData();
            Calendar lastDate = FCTran.numToDate(latestData.m_date);
            if (cycle < 1440)
            {
                newCycleData.m_date = FCTran.getDateNum(lastDate.get(Calendar.YEAR), lastDate.get(Calendar.MONTH) + 1, lastDate.get(Calendar.DAY_OF_MONTH), lastDate.get(Calendar.HOUR_OF_DAY), lastDate.get(Calendar.MINUTE), 0, 0);
            }
            else
            {
                newCycleData.m_date = FCTran.getDateNum(lastDate.get(Calendar.YEAR), lastDate.get(Calendar.MONTH) + 1, lastDate.get(Calendar.DAY_OF_MONTH), 0, 0, 0, 0);
            }
            newCycleData.m_close = latestData.m_close;
            newCycleData.m_high = latestData.m_close;
            newCycleData.m_low = latestData.m_close;
            newCycleData.m_open = latestData.m_close;
            newCycleData.m_volume = latestData.m_volume - tickDataCache.m_lastVolume;
            newCycleData.m_amount = latestData.m_amount - tickDataCache.m_lastAmount;
            oldDatas.add(newCycleData);
        }
        else
        {
            if (oldDatas.size() > 0)
            {
                SecurityData lastCycleData = oldDatas.get(oldDatas.size() - 1);
                if (dCycle == 0)
                {
                    double newData = FCTran.getDateNum(newDate.get(Calendar.YEAR), newDate.get(Calendar.MONTH) + 1, newDate.get(Calendar.DAY_OF_MONTH), newDate.get(Calendar.HOUR_OF_DAY), newDate.get(Calendar.MINUTE), 0, 0);
                    for (int i = 0; i < oldDatas.size(); i++)
                    {
                        SecurityData oData = oldDatas.get(i);
                        if (oData.m_date == newData)
                        {
                            oData.m_open = latestData.m_open;
                            lastCycleData = oData;
                            break;
                        }
                    }
                }
                lastCycleData.m_close = latestData.m_close;
                if (lastCycleData.m_high < latestData.m_close)
                {
                    lastCycleData.m_high = latestData.m_close;
                }
                if (lastCycleData.m_low > lastCycleData.m_close)
                {
                    lastCycleData.m_low = latestData.m_close;
                }
                lastCycleData.m_amount += latestData.m_amount - tickDataCache.m_lastAmount;
                lastCycleData.m_volume += latestData.m_volume - tickDataCache.m_lastVolume;
            }
        }
        tickDataCache.m_code = code;
        tickDataCache.m_lastAmount = latestData.m_amount;
        tickDataCache.m_lastDate = latestData.m_date;
        tickDataCache.m_lastVolume = latestData.m_volume;
    }

    public static HashMap<String, ArrayList<ADJUSTMENTFACTOR>> m_factors = new HashMap<String, ArrayList<ADJUSTMENTFACTOR>>();

    public static double fq_price_func(double price, ADJUSTMENTFACTOR factor)
    {
        float cash_bt = factor.f1;
        float bonus_shr = factor.f3;
        float allot_pct = factor.f4;
        float allot_price = factor.f2;
        return (10.0 * price - cash_bt + allot_pct * allot_price) / (10.0 + allot_pct + bonus_shr);
    }

    public static double fq_price_func2(double price, ADJUSTMENTFACTOR factor)
    {
        float cash_bt = factor.f1;
        float bonus_shr = factor.f3;
        float allot_pct = factor.f4;
        float allot_price = factor.f2;
        return (price * (10.0 + allot_pct + bonus_shr) - allot_pct * allot_price + cash_bt) / 10.0;
    }

    /*
     * 转换前复权
     *@param code
     *@param kd
     */
    public static void ConvertXDRBeforePrice(String code, SecurityData kd, double trade_date, ArrayList<ADJUSTMENTFACTOR> factor)
    {
        int size = factor.size();
        if (size > 0)
        {
            int pos = 0;
            double date = kd.m_date;
            if (kd.m_date < factor.get(factor.size() - 1).dwDate)
            {
                for (int i = 0; i < size; i++)
                {
                    if (trade_date > 0 && trade_date < factor.get(i).dwDate)
                    {
                        continue;
                    }
                    pos = i;
                    if (date < factor.get(i).dwDate)
                    {
                        break;
                    }
                }
                for (int i = pos; i < size; i++)
                {
                    if (trade_date > 0 && trade_date < factor.get(i).dwDate)
                    {
                        continue;
                    }
                    kd.m_open = fq_price_func(kd.m_open, factor.get(i));
                    kd.m_high = fq_price_func(kd.m_high, factor.get(i));
                    kd.m_low = fq_price_func(kd.m_low, factor.get(i));
                    kd.m_close = fq_price_func(kd.m_close, factor.get(i));
                }
            }
        }
    }

    /*
     * 转换后复权
     *@param code
     *@param kd
     */
    public static void ConvertXDRAfterPrice(String code, SecurityData kd, double trade_date, ArrayList<ADJUSTMENTFACTOR> factor)
    {
        int size = factor.size();
        if (size > 0)
        {
            double date = kd.m_date;
            ArrayList<ADJUSTMENTFACTOR> factors = new ArrayList<ADJUSTMENTFACTOR>();
            for (int i = 0; i < size; i++)
            {
                if (date < factor.get(i).dwDate)
                {
                    break;
                }
                else
                {
                    factors.add(0, factor.get(i));
                }
            }
            for (int i = 0; i < factors.size(); i++)
            {
                kd.m_open = fq_price_func2(kd.m_open, factors.get(i));
                kd.m_high = fq_price_func2(kd.m_high, factors.get(i));
                kd.m_low = fq_price_func2(kd.m_low, factors.get(i));
                kd.m_close = fq_price_func2(kd.m_close, factors.get(i));
            }
            factors.clear();
        }
    }

    public static void ConvertXDR(String code, int rights_offering, ArrayList<SecurityData> datas)
    {
        if (m_factors.containsKey(code))
        {
            ArrayList<ADJUSTMENTFACTOR> factor = m_factors.get(code);
            int datasSize = datas.size();
            if (datasSize > 0)
            {
                double trade_date = datas.get(datas.size() - 1).m_date;
                // 复权K线
                for (int i = 0; i < datasSize; ++i)
                {
                    SecurityData kd = datas.get(i);
                    if (rights_offering == 1)
                    {
                        ConvertXDRBeforePrice(code, kd, trade_date, factor);
                    }
                    else if (rights_offering == 2)
                    {
                        ConvertXDRAfterPrice(code, kd, trade_date, factor);
                    }
                }
            }
        }
    }

    public static void multiMinuteSecurityDatas(ArrayList<SecurityData> newDatas, ArrayList<SecurityData> minuteDatas, int cycle)
    {
        int lastMinutes = 0;
        if (cycle > 0)
        {
//            newDatas.Capacity = minuteDatas.size() / cycle;
        }
        for (int i = 0; i < minuteDatas.size(); i++)
        {
            SecurityData minuteData = minuteDatas.get(i);
            int minutes = (int)(minuteData.m_date / 60);
            if (lastMinutes == 0)
            {
                lastMinutes = minutes;
            }
            //更新
            if (newDatas.size() > 0 && minutes - lastMinutes < cycle)
            {
                SecurityData lastData = newDatas.get(newDatas.size() - 1);
                lastData.m_close = minuteData.m_close;
                if (minuteData.m_high > lastData.m_high)
                {
                    lastData.m_high = minuteData.m_high;
                }
                if (minuteData.m_low < lastData.m_low)
                {
                    lastData.m_low = minuteData.m_low;
                }
                lastData.m_amount += minuteData.m_amount;
                lastData.m_volume += minuteData.m_volume;
                lastData.m_endDate = minuteData.m_date;
            }
            else
            {
                SecurityData newData = new SecurityData();
                newData.m_date = minuteData.m_date;
                newData.m_high = minuteData.m_high;
                newData.m_low = minuteData.m_low;
                newData.m_open = minuteData.m_open;
                newData.m_close = minuteData.m_close;
                newData.m_amount = minuteData.m_amount;
                newData.m_volume = minuteData.m_volume;
                newData.m_startDate = minuteData.m_date;
                newData.m_endDate = minuteData.m_date;
                newDatas.add(newData);
                lastMinutes = minutes;
            }
        }
    }

    public static int getHistoryWeekDatas(ArrayList<SecurityData> weekDatas, ArrayList<SecurityData> dayDatas)
    {
        int dayDatasSize = dayDatas.size();
//        weekDatas.Capacity = dayDatas.size() / 4;
        if (dayDatasSize > 0)
        {
            double firstDate = FCTran.getDateNum(1970, 1, 5, 0, 0, 0, 0);
            SecurityData weekData = new SecurityData();
            weekData.copy(dayDatas.get(0));
            weekData.m_startDate = weekData.m_date;
            int lWeeks = (int)((weekData.m_date - firstDate) / 86400 / 7);
            for (int i = 0; i < dayDatasSize; i++)
            {
                SecurityData dayData = new SecurityData();
                dayData.copy(dayDatas.get(i));
                int weeks = (int)((dayData.m_date - firstDate) / 86400 / 7);
                boolean isNextWeek = false;
                if (weeks > lWeeks)
                {
                    isNextWeek = true;
                }
                if (isNextWeek)
                {
                    weekDatas.add(weekData);
                    weekData = dayData;
                    weekData.m_startDate = weekData.m_date;
                    if (i == dayDatasSize - 1)
                    {
                        weekData.m_endDate = dayData.m_date;
                        weekDatas.add(weekData);
                    }
                }
                else
                {
                    if (i > 0)
                    {
                        weekData.m_endDate = dayData.m_date;
                        weekData.m_close = dayData.m_close;
                        weekData.m_amount += dayData.m_amount;
                        weekData.m_volume += dayData.m_volume;
                        if (weekData.m_high < dayData.m_high)
                        {
                            weekData.m_high = dayData.m_high;
                        }
                        if (weekData.m_low > dayData.m_low)
                        {
                            weekData.m_low = dayData.m_low;
                        }
                    }
                    if (i == dayDatasSize - 1)
                    {
                        weekData.m_endDate = dayData.m_date;
                        weekDatas.add(weekData);
                    }
                }
                lWeeks = weeks;
            }
        }
        return 1;
    }

    public static int getHistoryMonthDatas(ArrayList<SecurityData> monthDatas, ArrayList<SecurityData> dayDatas)
    {
        int dayDatasSize = dayDatas.size();
        if (dayDatasSize > 0)
        {
//            monthDatas.Capacity = dayDatas.size() / 20;
            SecurityData monthData = new SecurityData();
            monthData.copy(dayDatas.get(0));
            monthData.m_startDate = monthData.m_date;
            Calendar ldate = FCTran.numToDate(monthData.m_date);
            int lYear = ldate.get(Calendar.YEAR); 
            int lMonth = ldate.get(Calendar.MONTH) + 1; 
            int lDay = ldate.get(Calendar.DAY_OF_MONTH); 
            int lHour = ldate.get(Calendar.HOUR_OF_DAY); 
            int lMinute = ldate.get(Calendar.MINUTE); 
            int lSecond = ldate.get(Calendar.SECOND);
            int lMs = ldate.get(Calendar.MILLISECOND);
//            FCTran.getDateByNum(monthData.m_date, ReflYear, ReflMonth, ReflDay, ReflHour, ReflMinute, ReflSecond, ReflMs);
            for (int i = 0; i < dayDatasSize; i++)
            {
                SecurityData dayData = new SecurityData();
                dayData.copy(dayDatas.get(i));
                Calendar date = FCTran.numToDate(dayData.m_date);
                int year = date.get(Calendar.YEAR); 
                int month = date.get(Calendar.MONTH) + 1; 
                int day = date.get(Calendar.DAY_OF_MONTH); 
                int hour = date.get(Calendar.HOUR_OF_DAY); 
                int minute = date.get(Calendar.MINUTE); 
                int second = date.get(Calendar.SECOND);
                int ms = date.get(Calendar.MILLISECOND);
                boolean isNextMonth = year * 12 + month > lYear * 12 + lMonth;
                if (isNextMonth)
                {
                    monthDatas.add(monthData);
                    monthData = dayData;
                    monthData.m_startDate = monthData.m_date;
                    if (i == dayDatasSize - 1)
                    {
                        monthData.m_endDate = dayData.m_date;
                        monthDatas.add(monthData);
                    }
                }
                else
                {
                    if (i > 0)
                    {
                        monthData.m_endDate = dayData.m_date;
                        monthData.m_close = dayData.m_close;
                        monthData.m_amount += dayData.m_amount;
                        monthData.m_volume += dayData.m_volume;
                        if (monthData.m_high < dayData.m_high)
                        {
                            monthData.m_high = dayData.m_high;
                        }
                        if (monthData.m_low > dayData.m_low)
                        {
                            monthData.m_low = dayData.m_low;
                        }
                    }
                    if (i == dayDatasSize - 1)
                    {
                        monthData.m_endDate = dayData.m_date;
                        monthDatas.add(monthData);
                    }
                }
                lYear = year;
                lMonth = month;
                lDay = day;
            }
        }
        return 1;
    }

    public static int getHistorySeasonDatas(ArrayList<SecurityData> seasonDatas, ArrayList<SecurityData> dayDatas)
    {
        int dayDatasSize = dayDatas.size();
        if (dayDatasSize > 0)
        {
//            seasonDatas.Capacity = dayDatas.size() / 60;
            SecurityData seaonData = new SecurityData();
            seaonData.copy(dayDatas.get(0));
            seaonData.m_startDate = seaonData.m_date;
            Calendar ldate = FCTran.numToDate(seaonData.m_date);
            int lYear = ldate.get(Calendar.YEAR); 
            int lMonth = ldate.get(Calendar.MONTH) + 1; 
            int lDay = ldate.get(Calendar.DAY_OF_MONTH); 
            int lHour = ldate.get(Calendar.HOUR_OF_DAY); 
            int lMinute = ldate.get(Calendar.MINUTE); 
            int lSecond = ldate.get(Calendar.SECOND);
            int lMs = ldate.get(Calendar.MILLISECOND);
            for (int i = 0; i < dayDatasSize; i++)
            {
                SecurityData dayData = new SecurityData();
                dayData.copy(dayDatas.get(i));
                Calendar date = FCTran.numToDate(dayData.m_date);
                int year = date.get(Calendar.YEAR); 
                int month = date.get(Calendar.MONTH) + 1; 
                int day = date.get(Calendar.DAY_OF_MONTH); 
                int hour = date.get(Calendar.HOUR_OF_DAY); 
                int minute = date.get(Calendar.MINUTE); 
                int second = date.get(Calendar.SECOND);
                int ms = date.get(Calendar.MILLISECOND);
                boolean isNextSeason = year * 4 + getSeason(month) > lYear * 4 + getSeason(lMonth);
                if (isNextSeason)
                {
                    seasonDatas.add(seaonData);
                    seaonData = dayData;
                    seaonData.m_startDate = seaonData.m_date;
                    if (i == dayDatasSize - 1)
                    {
                        seaonData.m_endDate = dayData.m_date;
                        seasonDatas.add(seaonData);
                    }
                }
                else
                {
                    if (i > 0)
                    {
                        seaonData.m_endDate = dayData.m_date;
                        seaonData.m_close = dayData.m_close;
                        seaonData.m_amount += dayData.m_amount;
                        seaonData.m_volume += dayData.m_volume;
                        if (seaonData.m_high < dayData.m_high)
                        {
                            seaonData.m_high = dayData.m_high;
                        }
                        if (seaonData.m_low > dayData.m_low)
                        {
                            seaonData.m_low = dayData.m_low;
                        }
                    }
                    if (i == dayDatasSize - 1)
                    {
                        seaonData.m_endDate = dayData.m_date;
                        seasonDatas.add(seaonData);
                    }
                }
                lYear = year;
                lMonth = month;
                lDay = day;
            }
        }
        return 1;
    }

    public static int getHistoryHalfYearDatas(ArrayList<SecurityData> halfYearDatas, ArrayList<SecurityData> dayDatas)
    {
        int dayDatasSize = dayDatas.size();
        if (dayDatasSize > 0)
        {
//            halfYearDatas.Capacity = dayDatas.size() / 120;
            SecurityData yearData = new SecurityData();
            yearData.copy(dayDatas.get(0));
            yearData.m_startDate = yearData.m_date;
            Calendar ldate = FCTran.numToDate(yearData.m_date);
            int lyear = ldate.get(Calendar.YEAR); 
            int lmonth = ldate.get(Calendar.MONTH) + 1; 
            int lday = ldate.get(Calendar.DAY_OF_MONTH); 
            int lhour = ldate.get(Calendar.HOUR_OF_DAY); 
            int lminute = ldate.get(Calendar.MINUTE); 
            int lsecond = ldate.get(Calendar.SECOND);
            int lms = ldate.get(Calendar.MILLISECOND);
            for (int i = 0; i < dayDatasSize; i++)
            {
                SecurityData dayData = new SecurityData();
                dayData.copy(dayDatas.get(i));
                Calendar date = FCTran.numToDate(dayData.m_date);
                int year = date.get(Calendar.YEAR); 
                int month = date.get(Calendar.MONTH) + 1; 
                int day = date.get(Calendar.DAY_OF_MONTH); 
                int hour = date.get(Calendar.HOUR_OF_DAY); 
                int minute = date.get(Calendar.MINUTE); 
                int second = date.get(Calendar.SECOND);
                int ms = date.get(Calendar.MILLISECOND);
                boolean isNextHalfYear = year * 2 + (month - 1) / 6 > lyear * 2 + (lmonth - 1) / 6;
                if (isNextHalfYear)
                {
                    halfYearDatas.add(yearData);
                    yearData = dayData;
                    yearData.m_startDate = yearData.m_date;
                    if (i == dayDatasSize - 1)
                    {
                        yearData.m_endDate = dayData.m_date;
                        halfYearDatas.add(yearData);
                    }
                }
                else
                {
                    if (i > 0)
                    {
                        yearData.m_endDate = dayData.m_date;
                        yearData.m_close = dayData.m_close;
                        yearData.m_amount += dayData.m_amount;
                        yearData.m_volume += dayData.m_volume;
                        if (yearData.m_high < dayData.m_high)
                        {
                            yearData.m_high = dayData.m_high;
                        }
                        if (yearData.m_low > dayData.m_low)
                        {
                            yearData.m_low = dayData.m_low;
                        }
                    }
                    if (i == dayDatasSize - 1)
                    {
                        yearData.m_endDate = dayData.m_date;
                        halfYearDatas.add(yearData);
                    }
                }
                lyear = year;
                lmonth = month;
                lday = day;
            }
        }
        return 1;
    }

    public static int getHistoryYearDatas(ArrayList<SecurityData> yearDatas, ArrayList<SecurityData> dayDatas)
    {
        int dayDatasSize = dayDatas.size();
        if (dayDatasSize > 0)
        {
//            yearDatas.Capacity = dayDatas.size() / 240;
            SecurityData yearData = new SecurityData();
            yearData.copy(dayDatas.get(0));
            yearData.m_startDate = yearData.m_date;
            Calendar ldate = FCTran.numToDate(yearData.m_date);
            int lyear = ldate.get(Calendar.YEAR); 
            int lmonth = ldate.get(Calendar.MONTH) + 1; 
            int lday = ldate.get(Calendar.DAY_OF_MONTH); 
            int lhour = ldate.get(Calendar.HOUR_OF_DAY); 
            int lminute = ldate.get(Calendar.MINUTE); 
            int lsecond = ldate.get(Calendar.SECOND);
            int lms = ldate.get(Calendar.MILLISECOND);
            for (int i = 0; i < dayDatasSize; i++)
            {
                SecurityData dayData = new SecurityData();
                dayData.copy(dayDatas.get(i));
                Calendar date = FCTran.numToDate(dayData.m_date);
                int year = date.get(Calendar.YEAR); 
                int month = date.get(Calendar.MONTH) + 1; 
                int day = date.get(Calendar.DAY_OF_MONTH); 
                int hour = date.get(Calendar.HOUR_OF_DAY); 
                int minute = date.get(Calendar.MINUTE); 
                int second = date.get(Calendar.SECOND);
                int ms = date.get(Calendar.MILLISECOND);
                boolean isNextYear = year > lyear;
                if (isNextYear)
                {
                    yearDatas.add(yearData);
                    yearData = dayData;
                    yearData.m_startDate = yearData.m_date;
                    if (i == dayDatasSize - 1)
                    {
                        yearData.m_endDate = dayData.m_date;
                        yearDatas.add(yearData);
                    }
                }
                else
                {
                    if (i > 0)
                    {
                        yearData.m_endDate = dayData.m_date;
                        yearData.m_close = dayData.m_close;
                        yearData.m_amount += dayData.m_amount;
                        yearData.m_volume += dayData.m_volume;
                        if (yearData.m_high < dayData.m_high)
                        {
                            yearData.m_high = dayData.m_high;
                        }
                        if (yearData.m_low > dayData.m_low)
                        {
                            yearData.m_low = dayData.m_low;
                        }
                    }
                    if (i == dayDatasSize - 1)
                    {
                        yearData.m_endDate = dayData.m_date;
                        yearDatas.add(yearData);
                    }
                }
                lyear = year;
                lmonth = month;
                lday = day;
            }
        }
        return 1;
    }
}
